package com.jianshuge.oauth;

import java.io.IOException;
import java.net.MalformedURLException;

import com.jianshuge.oauth.DoubanDialog;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.CookieSyncManager;

/**
 * Encapsulation main douban auth login APIs
 * @author yunlong.lee@163.com
 */
public class Douban {

    public static String SERVER = "https://www.douban.com/service/auth2/";
    public static String URL_OAUTH2_ACCESS_AUTHORIZE = "https://www.douban.com/service/auth2/auth";
    public static String URL_OAUTH2_ACCESS_TOKEN = "https://www.douban.com/service/auth2/token";


    private static String APP_KEY = "";
    private static String APP_SECRET = "";

    private static Douban mWeiboInstance = null;
    private Token mAccessToken = null;

    private OAuthDialogListener mAuthDialogListener;

    private static final int DEFAULT_AUTH_ACTIVITY_CODE = 32973;

    public static final String ACCESS_TOKEN 	= "access_token";
    public static final String EXPIRES_IN 	= "expires_in";
    public static final String REFRESH_TOKEN 	= "refresh_token";

    public static final String DEFAULT_REDIRECT_URI = "wbconnect://success";// 暂不支持
    public static final String DEFAULT_CANCEL_URI = "wbconnect://cancel";// 暂不支持

    private String mRedirectUrl;

    private Douban() {
        Utility.setRequestHeader("Accept-Encoding", "gzip");
        mRedirectUrl = DEFAULT_REDIRECT_URI;
    }

    public synchronized static Douban getInstance() {
        if (mWeiboInstance == null) {
            mWeiboInstance = new Douban();
        }
        return mWeiboInstance;
    }

    // 设置accessToken
    public void setAccessToken(AccessToken token) {
        mAccessToken = token;
    }

    public Token getAccessToken() {
        return this.mAccessToken;
    }

    public void setupConsumerConfig(String consumer_key, String consumer_secret) {
    	Douban.APP_KEY = consumer_key;
    	Douban.APP_SECRET = consumer_secret;
    }

    public static String getAppKey() {
        return Douban.APP_KEY;
    }

    public static String getAppSecret() {
        return Douban.APP_SECRET;
    }

    public static String getSERVER() {
        return SERVER;
    }

    public static void setSERVER(String sERVER) {
        SERVER = sERVER;
    }

    public String getRedirectUrl() {
        return mRedirectUrl;
    }

    public void setRedirectUrl(String mRedirectUrl) {
        this.mRedirectUrl = mRedirectUrl;
    }

    /**
     * 获取Oauth2.0的accesstoken
     * https://www.douban.com/service/auth2/token?
     * client_id=0b5405e19c58e4cc21fc11a4d50aae64& 
  	 * client_secret=edfc4e395ef93375&
  	 * redirect_uri=https://www.example.com/back&
  	 * grant_type=authorization_code&
  	 * code=9b73a4248
     * 
     * @param context
     * @param app_key
     * @param app_secret
     * @param usrname
     * @param password
     * @return
     * @throws OAuthException
     */
    public String getOauth2AccessToken(Context context, String auth_code ) throws OAuthException {

        Utility.setAuthorization(new OAuth2AccessTokenHeader());
        OAuthParameters postParams = new OAuthParameters();
        postParams.add("client_id", APP_KEY);
        postParams.add("client_secret", APP_SECRET);
        postParams.add("redirect_uri", mRedirectUrl);
        postParams.add("grant_type", "authorization_code");
        postParams.add("code", auth_code);
        
        String rlt = Utility.openUrl(context, Douban.URL_OAUTH2_ACCESS_TOKEN, "POST", postParams, null);

        return rlt;
    }

    private boolean startSingleSignOn(Activity activity, String applicationId,
            String[] permissions, int activityCode) {
        return false;
    }

    private void startDialogAuth(Activity activity, String[] permissions) {
        OAuthParameters params = new OAuthParameters();
 
        if (permissions.length > 0) {
            params.add("scope", TextUtils.join(",", permissions));
        }
        
        CookieSyncManager.createInstance(activity);
        dialog(activity, params, new OAuthDialogListener() {

            public void onComplete(Bundle values) {
                // ensure any cookies set by the dialog are saved
                CookieSyncManager.getInstance().sync();                
                
                if (null == mAccessToken) {
                    mAccessToken = new Token();
                }
                mAccessToken.setToken( values.getString(ACCESS_TOKEN) );
                mAccessToken.setExpiresIn( values.getString(EXPIRES_IN) );
                mAccessToken.setRefreshToken(values.getString(REFRESH_TOKEN));
                
                if (isSessionValid()) {
                    Log.d(
                    	"Weibo-authorize", 
                    	"Login Success! access_token=" + mAccessToken.getToken() + " expires="
                        + mAccessToken.getExpiresIn()
                    );
                    mAuthDialogListener.onComplete(values);
                } else {	
                    Log.d("Weibo-authorize", "Failed to receive access token");
                    mAuthDialogListener.onAuthException(new OAuthException("Failed to receive access token."));
                }
            }

            public void onError(OAuthDialogError error) {
                Log.d("Weibo-authorize", "Login failed: " + error);
                mAuthDialogListener.onError(error);
            }

            public void onAuthException(OAuthException error) {
                Log.d("Weibo-authorize", "Login failed: " + error);
                mAuthDialogListener.onAuthException(error);
            }

            public void onCancel() {
                Log.d("Weibo-authorize", "Login canceled");
                mAuthDialogListener.onCancel();
            }
        });
    }

    /**
     * User-Agent Flow
     * 
     * @param activity
     * 
     * @param listener
     *            授权结果监听器
     */
    public void authorize(Activity activity, final OAuthDialogListener listener) {
        authorize(activity, new String[] {}, DEFAULT_AUTH_ACTIVITY_CODE, listener);
    }

    private void authorize(Activity activity, String[] permissions, final OAuthDialogListener listener) {
        authorize(activity, permissions, DEFAULT_AUTH_ACTIVITY_CODE, listener);
    }

    private void authorize(Activity activity, String[] permissions, int activityCode, final OAuthDialogListener listener) {
        Utility.setAuthorization(new OAuth2AccessTokenHeader());

        boolean singleSignOnStarted = false;
        mAuthDialogListener = listener;

        // Prefer single sign-on, where available.
        if (activityCode >= 0) {
            singleSignOnStarted = startSingleSignOn(activity, APP_KEY, permissions, activityCode);
        }
        
        // Otherwise fall back to traditional dialog.
        if (!singleSignOnStarted) {
            startDialogAuth(activity, permissions);
        }

    }

    private void authorizeCallBack(int requestCode, int resultCode, Intent data) {

    }
    
    /***
    https://www.douban.com/service/auth2/auth?
    	  client_id=0b5405e19c58e4cc21fc11a4d50aae64&
    	  redirect_uri=https://www.example.com/back&
    	  response_type=code&
    	  scope=douban_basic_common
   	***/
    public void dialog(Context context, OAuthParameters parameters, final OAuthDialogListener listener) {
        parameters.add("client_id", APP_KEY);
        parameters.add("redirect_uri", mRedirectUrl);
        parameters.add("response_type", "code");
        parameters.add("scope", "douban_basic_common");
        parameters.add("display", "mobile");

        if (isSessionValid()) {
            parameters.add(ACCESS_TOKEN, mAccessToken.getToken());
        }
        String url = URL_OAUTH2_ACCESS_AUTHORIZE + "?" + Utility.encodeUrl(parameters);
        
        System.out.println( url );
        
        if (context.checkCallingOrSelfPermission(Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED) {
            Utility.showAlert(context, "Error",
                    "Application requires permission to access the Internet");
        } else {
            new DoubanDialog(this, context, url, listener).show();
        }
    }

    public boolean isSessionValid() {
        if (mAccessToken != null) {
        	System.out.println("Token is " + mAccessToken.getToken());
        	System.out.println("ExpiresIn is " + mAccessToken.getExpiresIn());
        	
            return ( 
            		!TextUtils.isEmpty(mAccessToken.getToken()) && 
            		(mAccessToken.getExpiresIn() == 0 || (System.currentTimeMillis() < mAccessToken.getExpiresIn()) )
            );
        }
        return false;
    }
}